﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Agile.Engine.Data;
using Agile.Engine.Utils;
using System.Data;

namespace Fis.Web.Rules.Book
{
    public class BillRule : DynamicRule
    {

        string Master = "TBILLMASTER";
        string Detail = "TBILLDETAIL";

        public int BillSequnce(string range)
        {
            var da = new DataAccess() { Context = Model.DataContext, TableName = Master };
            return da.Scalar(0, "MAX(FNO)", string.Format("DATEPART(month, FENTERDATE) = {0}", range)) + 1;
        }

        void AddNew(System.Data.DataRow mst, System.Data.DataRow[] dtl)
        {
            var type = Paramater["SyncType"].ToString();
            if (type != "init")
            {
                mst["FNO"] = BillSequnce(BookRange);
            }
            mst["FSYNC"] = 1;

            mst["SINDEXDATE"] = DateTime.Now;
            mst["SBOOKID"] = BookID;
            mst.AcceptChanges();
            mst.SetAdded();

            var data = dtl.CopyToDataTable();
            data.TableName = Detail;
            foreach (var d in data.AsEnumerable())
            {

                var valid = Model.Count("TACCOUNT", "SID", string.Format("FPARENT='{0}'", d["FACCOUNTCODE"]));

                if (valid > 0)
                {
                    Message = string.Format("科目{0}不是最子级科目", d["FACCOUNTCODE"]);
                    throw new Exception(Message);
                }

                d["SINDEXDATE"] = DateTime.Now;
                d["SBOOKID"] = BookID;

                d.AcceptChanges();
                d.SetAdded();
            }


            Model.UpdateTable(Master, "SID", mst);
            Model.UpdateTable(data);
        }

        void Modify(System.Data.DataRow mst, System.Data.DataRow[] dtl)
        {
            mst["SINDEXDATE"] = DateTime.Now;
            mst.AcceptChanges();
            mst.SetModified();

            var hashcode = mst["SID"].ToString().GetHashCode();
            var sequnce = 0;

            foreach (var d in dtl.AsEnumerable())
            {
                var valid = Model.Count("TACCOUNT", "SID", string.Format("FPARENT='{0}'", d["FACCOUNTCODE"]));

                if (valid > 0)
                {
                    Message = string.Format("科目{0}不是最子级科目", d["FACCOUNTCODE"]);
                    throw new Exception(Message);
                }

                d["SID"] = string.Format("{0}-{1:0000#}", hashcode, ++sequnce);
                d["FVCHID"] = mst["SID"].ToString();
                d["SINDEXDATE"] = DateTime.Now;

                d.AcceptChanges();
                d.SetAdded();
            }

            var detailupdate = Model.QueryTable(Detail, "1=2");
            dtl.CopyToDataTable(detailupdate, LoadOption.Upsert);
            Model.UpdateTable(Master, "SID", mst);
            Model.Delete(Detail, string.Format("FVCHID='{0}'", mst["SID"]));
            Model.UpdateTable(detailupdate, Detail, string.Format("FVCHID='{0}'", mst["SID"]));
        }

        void Delete(string sid)
        {
            var fno = Model.ExecuteScalar(0, "SELECT FNO FROM TBILLMASTER WHERE SID='" + sid + "'");
            Model.Delete(Master, "SID='" + sid + "'");
            Model.Delete(Detail, "FVCHID='" + sid + "'");

            //删除后凭证号前移
            Model.ExecuteNonQuery(string.Format(
                @"UPDATE {0} SET FNO=FNO-1, SINDEXDATE=GETDATE() WHERE FNO>={1} AND DATEPART(month, FENTERDATE) = {2}"
                , Master
                , fno
                , BookRange));

            CommonRule common = new CommonRule();
            common.UpdateDeleteInfo(Model.DataContext, Master, sid, BookID);
            common.UpdateDeleteInfo(Model.DataContext, Detail, sid, BookID);

        }

        void Sync(System.Data.DataTable mst, System.Data.DataTable dtl)
        {
            foreach (var d in mst.AsEnumerable())
            {
                AddNew(d, dtl.Select(string.Format("FVCHID='{0}'", d["SID"])));
            }
        }

        void ValidateBill(DataTable master)
        {
            var book = Model.QueryTable("TBOOK").Rows[0];
            var range = int.Parse(book["FBOOKRANGE"].ToString());

            //未初始化可提交任意期间数据,否则只能提交当前期间以后的数据
            if (book["FBOOKINITIALIZED"].Equals(1))
            {
                foreach (var d in master.AsEnumerable())
                {
                    if (DateTime.Parse(d["FENTERDATE"].ToString()).Month < range)
                        throw new Exception("凭证录入日期不在当前期间。");
                } 
            }
        }

        public override void ExecuteNonTrans()
        {
            var action = Paramater["Action"].ToString();
            System.Data.DataTable mst = null, dtl = null;
            Status = 1;

            switch (action)
            {
                case "AddNew":
                    mst = ZipUtils.UnZipDataTable(Paramater["master"].ToString());
                    dtl = ZipUtils.UnZipDataTable(Paramater["detail"].ToString());
                    ValidateBill(mst);
                    AddNew(mst.Rows[0], dtl.Select());
                    break;
                case "Modify":
                    mst = ZipUtils.UnZipDataTable(Paramater["master"].ToString());
                    dtl = ZipUtils.UnZipDataTable(Paramater["detail"].ToString());
                    Modify(mst.Rows[0], dtl.Select());
                    ValidateBill(mst);

                    break;
                case "Delete":
                    Delete(Paramater["SID"].ToString());
                    break;
                case "Sync":
                    mst = ZipUtils.UnZipDataTable(Paramater["master"].ToString());
                    dtl = ZipUtils.UnZipDataTable(Paramater["detail"].ToString());
                    ValidateBill(mst);
                    Sync(mst, dtl);
                    break;
            }

            if (mst != null)
            {
                Result["master"] = ZipUtils.ZipDataTable(mst);
                Result["detail"] = ZipUtils.ZipDataTable(dtl);
            }

        }
    }
}
